package maggames.core.interfaces;

import java.util.Properties;

import maggames.core.GameState;
import maggames.core.GameTurn;
import maggames.core.Player;
import maggames.core.exceptions.UnIntializedException;

/**
 * The central game engine object.  Implementing objects form the basis for a given game by creating the game internal
 * board, managing user turns, setup, and game state transitions.  The game engine also defines how a game can be won
 * and whether or not a given turn is valid and/or can be performed.
 * 
 * @author BenjaminPLee
 * @version 1.0
 */
public interface GameEngine {
	
	/**
	 * Intialize the game engine.  Implementing games can require various properties to be passed with the method call.
	 * This method must be called prior to the other methods.  Implementation requiring properties should have built in
	 * defaults is possible.
	 * 
	 * @param props Properties object contain implementation specific properties
	 */
	public abstract void initialize(Properties props);
	
	/**
	 * Returns the current game board state
	 * 
	 * @return the current board state
	 * @throws UnIntializedException thrown if the engine has not yet been initialized
	 */
	public abstract GameBoard getGameBoard();
	
	/**
	 * Returns the current game state
	 * 
	 * @return the current game state
	 * @throws UnIntializedException thrown if the engine has not yet been initialized
	 */
	public abstract GameState getGameState();
	
	/**
	 * Returns the current player whose turn it is
	 * 
	 * @return the current player
	 * @throws UnIntializedException thrown if the engine has not yet been initialized
	 */
	public abstract Player getCurrentPlayer();
	
	/**
	 * Requests that the given turn be taken on the current board.  If the turn is determined to be valid, then the turn
	 * is executed, game state changed accordingly, and any rule induced moves returned to the calling method.  If the turn
	 * is determined to be invalid, then the method will return false and the invalid move flagged.
	 * 
	 * @param turn the requested turn to be taken
	 * @return if turn was valid or not
	 * @throws UnIntializedException thrown if the engine has not yet been initialized
	 */
	public abstract boolean takeTurn(GameTurn turn);
	

	/**
	 * Determines if the given game turn is valid within the scope and rules of the game engine.  If a game turn is valid,
	 * the method returns true.  If the turn is deemed invalid, then the method returns false, and the first invalid move
	 * is identified within the given turn object.
	 * 
	 * @param turn a game turn needing to be validated
	 * @return boolean representing the overall validity of the given turn
	 * @throws UnIntializedException thrown if the engine has not yet been initialized
	 */
	public abstract boolean checkTurn(GameTurn turn);

	/**
	 * Checks to see if the current board state and data is in a winning configuration.  If so, the method returns the
	 * winning player's object.  If no player has won, the Player.NONE object is returned.
	 * 
	 * @return the winning player
	 * @throws UnIntializedException thrown if the engine has not yet been initialized
	 */
	public abstract Player checkForWin();
	
	/**
	 * Performs clean up operations on the current game state objects.
	 * 
	 * @throws UnIntializedException thrown if the engine has not yet been initialized
	 */
	public abstract void cleanUpGame();
}